import serial
import re
import random
import ssl
from datetime import datetime, timedelta
from paho.mqtt import client as mqtt_client
import json  # 导入 JSON 模块

# MQTT设置
broker = 'n12ebcd2.ala.cn-hangzhou.emqxsl.cn'
port = 8883
topic = "message"
client_id = f'python-mqtt-{random.randint(0, 1000)}'
username = 'emqx'
password = '123456'

# GPS变量
utctime = ''
lat = ''
ulat = ''
lon = ''
ulon = ''
numSv = ''
msl = ''
gps_t = 0

# 连接GPS串口
ser = serial.Serial("COM3", 9600, timeout=1)

if ser.isOpen():
    print("GPS串口已打开! 波特率=9600")
else:
    print("GPS串口打开失败!")


# MQTT连接函数
def connect_mqtt():
    def on_connect(client, userdata, flags, rc):
        if rc == 0:
            print("Connected to MQTT Broker!")
        else:
            print("Failed to connect, return code %d\n", rc)

    client = mqtt_client.Client(client_id)
    client.username_pw_set(username, password)
    client.on_connect = on_connect
    client.tls_set(certfile=None, keyfile=None, cert_reqs=ssl.CERT_NONE, tls_version=ssl.PROTOCOL_TLSv1_2)
    client.connect(broker, port)
    return client


# 发布GPS坐标到MQTT
def publish_data(client, lat, lon, msl, beijing_time_str):
    msg = json.dumps({"lon": lon, "lat": lat, "msl": msl, "beijing_time_str": beijing_time_str})  # 转换为 JSON 格式
    result = client.publish(topic, msg)
    status = result[0]
    if status == 0:
        print(f"Send `{msg}` to topic `{topic}`")
    else:
        print(f"Failed to send message to topic {topic}")


# 将GPS数据转换为度
def Convert_to_degrees(in_data1, in_data2):
    len_data1 = len(in_data1)
    str_data2 = "%05d" % int(in_data2)
    temp_data = int(in_data1)
    symbol = 1
    if temp_data < 0:
        symbol = -1
    degree = int(temp_data / 100.0)
    str_decimal = str(in_data1[len_data1 - 2]) + str(in_data1[len_data1 - 1]) + str(str_data2)
    f_degree = int(str_decimal) / 60.0 / 100000.0
    if symbol > 0:
        result = degree + f_degree
    else:
        result = degree - f_degree
    return result


# 读取GPS数据
def GPS_read():
    global utctime, lat, ulat, lon, ulon, numSv, msl, gps_t
    if ser.inWaiting():
        if ser.read(1) == b'G':
            if ser.inWaiting():
                if ser.read(1) == b'N':
                    if ser.inWaiting():
                        choice = ser.read(1)
                        if choice == b'G':
                            if ser.inWaiting():
                                if ser.read(1) == b'G':
                                    if ser.inWaiting():
                                        if ser.read(1) == b'A':
                                            GGA = ser.read(70)
                                            GGA_g = re.findall(r"\w+(?=,)|(?<=,)\w+", str(GGA))
                                            if len(GGA_g) < 13:
                                                print("未找到GPS数据")
                                                gps_t = 0
                                                return 0
                                            else:
                                                utctime = GGA_g[0]
                                                lat = "%.8f" % Convert_to_degrees(str(GGA_g[2]), str(GGA_g[3]))
                                                ulat = GGA_g[4]
                                                lon = "%.8f" % Convert_to_degrees(str(GGA_g[5]), str(GGA_g[6]))
                                                ulon = GGA_g[7]
                                                numSv = GGA_g[9]
                                                msl = GGA_g[12] + '.' + GGA_g[13] + GGA_g[14]
                                                gps_t = 1
                                                return 1


# 主循环
def run():
    client = connect_mqtt()
    client.loop_start()
    while True:
        if GPS_read():
            utc_time = datetime.strptime(utctime, '%H%M%S')
            beijing_time = utc_time + timedelta(hours=8)
            beijing_time_str = beijing_time.strftime('%H:%M:%S')
            print("*********************")
            print('北京时间: ' + beijing_time_str)
            print('海平面高度: ' + msl)
            print('WGS-84 坐标: 经度: ' + lon + ' 纬度: ' + lat)

            # 发布到MQTT
            publish_data(client, lat, lon, msl, beijing_time_str)

            print("*********************")


if __name__ == '__main__':
    run()
